#include "stdafx.h"

#include "bochs.h"


float_status_t FPU_pre_exception_handling(Bit16u control_word)
{
  float_status_t status;

  int precision = control_word & FPU_CW_PC;
 
  switch(precision)
  {
     case FPU_PR_32_BITS:
       status.float_rounding_precision = 32;
       break;
     case FPU_PR_64_BITS:
       status.float_rounding_precision = 64;
       break;
     case FPU_PR_80_BITS:
       status.float_rounding_precision = 80;
       break;
     default:
       status.float_rounding_precision = 80;
  }

  status.float_exception_flags = 0; // clear exceptions before execution
  status.float_nan_handling_mode = float_first_operand_nan;
  status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10;
  status.flush_underflow_to_zero = 0;

  return status;
}

void IA32_CPU::FADD_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FADD_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());
  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FADD_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(IA32_READ_FPU_REG(0), 
		float32_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FADD_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(IA32_READ_FPU_REG(0), 
		float64_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIADD_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80((Bit32s)(load_reg));

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIADD_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80(load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_add(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FMUL_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FMUL_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());
  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FMUL_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(IA32_READ_FPU_REG(0), 
		float32_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FMUL_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(IA32_READ_FPU_REG(0), 
		float64_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIMUL_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80((Bit32s)(load_reg));

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIMUL_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80(load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_mul(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUB_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUBR_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUB_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());

  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FSUBR_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());

  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FSUB_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(IA32_READ_FPU_REG(0), 
		float32_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUBR_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(float32_to_floatx80(load_reg, status), 
		IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUB_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(IA32_READ_FPU_REG(0), 
		float64_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSUBR_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(float64_to_floatx80(load_reg, status), 
		IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FISUB_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80((Bit32s)(load_reg));

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FISUBR_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = int32_to_floatx80((Bit32s)(load_reg));
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FISUB_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80(load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(IA32_READ_FPU_REG(0), 
	      int32_to_floatx80(load_reg), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FISUBR_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = int32_to_floatx80(load_reg);
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sub(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIV_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIVR_ST0_STj(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(0);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIV_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(i->rm());
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());
  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FDIVR_STi_ST0(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  int pop_stack = i->b1() & 2;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_stack_underflow(i->rm(), pop_stack);
     return;
  }

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = IA32_READ_FPU_REG(i->rm());

  float_status_t status = 
	FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, i->rm());
  if (pop_stack) 
      the_i387.FPU_pop();
}

void IA32_CPU::FDIV_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(IA32_READ_FPU_REG(0), 
		float32_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIVR_SINGLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float32 load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(float32_to_floatx80(load_reg, status), 
		IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIV_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(IA32_READ_FPU_REG(0), 
		float64_to_floatx80(load_reg, status), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FDIVR_DOUBLE_REAL(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  float64 load_reg;
  read_virtual_qword(i->seg(), IA32_RMAddr(i), &load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(float64_to_floatx80(load_reg, status), 
		IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIDIV_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80((Bit32s)(load_reg));

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIDIVR_WORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit16s load_reg;
  read_virtual_word(i->seg(), IA32_RMAddr(i), (Bit16u*)(&load_reg));

  floatx80 a = int32_to_floatx80((Bit32s)(load_reg));
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIDIV_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = IA32_READ_FPU_REG(0);
  floatx80 b = int32_to_floatx80(load_reg);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FIDIVR_DWORD_INTEGER(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_stack_underflow(0);
     return;
  }

  Bit32s load_reg;
  read_virtual_dword(i->seg(), IA32_RMAddr(i), (Bit32u*)(&load_reg));

  floatx80 a = int32_to_floatx80(load_reg);
  floatx80 b = IA32_READ_FPU_REG(0);

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_div(a, b, status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

void IA32_CPU::FSQRT(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
      FPU_stack_underflow(0);
     return;
  }

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_sqrt(IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}

/* D9 FC */
void IA32_CPU::FRNDINT(Ia32_Instruction_c *i)
{
   prepareFPU(i);

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
      FPU_stack_underflow(0);
     return;
  }

  float_status_t status = 
      FPU_pre_exception_handling( the_i387.get_control_word());

  floatx80 result = floatx80_round_to_int(IA32_READ_FPU_REG(0), status);

  if ( FPU_exception(status.float_exception_flags))
      return;

  IA32_WRITE_FPU_REG(result, 0);
}
